package com.talkweb.osmharmony.views.overlay.mylocation;

import com.talkweb.osmharmony.api.IMapView;
import com.talkweb.osmharmony.util.Log;
import com.talkweb.osmharmony.util.NetworkLocationIgnorer;
import ohos.app.Context;
import ohos.location.Location;
import ohos.location.Locator;
import ohos.location.LocatorCallback;
import ohos.location.RequestParam;

/**
 * location provider, by default, uses ohos.location.Locator#GPS_PROVIDER} and LocationManager NETWORK_PROVIDER}
 */
public class GpsMyLocationProvider implements IMyLocationProvider, LocatorCallback {
    private Locator mLocationManager;
    private Location mLocation;

    private IMyLocationConsumer mMyLocationConsumer;
    private long mLocationUpdateMinTime = 0;
    private float mLocationUpdateMinDistance = 0.0f;
    private NetworkLocationIgnorer mIgnorer = new NetworkLocationIgnorer();

    public GpsMyLocationProvider(Context context) {
        mLocationManager = new Locator(context);
    }

    // ===========================================================
    // Getter & Setter
    // ===========================================================

    public long getLocationUpdateMinTime() {
        return mLocationUpdateMinTime;
    }

    /**
     * Set the minimum interval for location updates. See
     * { LocationManager#requestLocationUpdates(String, long, float, LocationListener)}. Note
     * that you should call this before calling {@link MyLocationNewOverlay#enableMyLocation()}.
     *
     * @param milliSeconds
     */
    public void setLocationUpdateMinTime(final long milliSeconds) {
        mLocationUpdateMinTime = milliSeconds;
    }

    public float getLocationUpdateMinDistance() {
        return mLocationUpdateMinDistance;
    }

    /**
     * Set the minimum distance for location updates. See
     * { LocationManager#requestLocationUpdates(String, long, float, LocationListener)}. Note
     * that you should call this before calling {@link MyLocationNewOverlay#enableMyLocation()}.
     *
     * @param meters
     */
    public void setLocationUpdateMinDistance(final float meters) {
        mLocationUpdateMinDistance = meters;
    }

    //
    // IMyLocationProvider
    //

    /**
     * Enable location updates and show your current location on the map. By default this will
     * request location updates as frequently as possible, but you can change the frequency and/or
     * distance by calling {@link #setLocationUpdateMinTime} and/or {@link
     * #setLocationUpdateMinDistance} before calling this method.
     */
    @Override
    public boolean startLocationProvider(IMyLocationConsumer myLocationConsumer) {
        mMyLocationConsumer = myLocationConsumer;
        boolean result = false;
        if(mLocationManager.isLocationSwitchOn()){
            result = true;
            RequestParam requestParam = new RequestParam(RequestParam.PRIORITY_FAST_FIRST_FIX, 1 , 1);
            mLocationManager.startLocating(requestParam, this);
        }
        return result;
    }

    @Override
    public void stopLocationProvider() {
        mMyLocationConsumer = null;
        if (mLocationManager != null) {
            try {
                mLocationManager.stopLocating(this);
            } catch (Throwable ex) {
                Log.w(IMapView.LOGTAG, "Unable to deattach location listener", ex);
            }
        }
    }

    @Override
    public Location getLastKnownLocation() {
        return mLocation;
    }

    @Override
    public void destroy() {
        stopLocationProvider();
        mLocation = null;
        mLocationManager = null;
        mMyLocationConsumer = null;
        mIgnorer = null;
    }

    //
    // LocationListener
    //

    @Override
    public void onLocationReport(final Location location) {
        if (mIgnorer == null) {
            Log.w(IMapView.LOGTAG, "GpsMyLocation provider, mIgnore is null, unexpected. Location update will be ignored");
            return;
        }
        if (location == null)
            return;

        // ignore temporary non-gps fix
        if (mIgnorer.shouldIgnore("", System.currentTimeMillis()))
            return;

        mLocation = location;
        if (mMyLocationConsumer != null)
            mMyLocationConsumer.onLocationChanged(mLocation, this);
    }

    @Override
    public void onStatusChanged(int type) {

    }

    @Override
    public void onErrorReport(int type) {

    }

}
